#ifndef CEAECCB5_B011_4AF9_818F_A8033FECDFE6
#define CEAECCB5_B011_4AF9_818F_A8033FECDFE6

#include <pthread.h>
#include <iostream>
#include <queue>
#include <unistd.h>

using namespace std;

template<class T>
class Blockqueue{
	static const int defaultnum = 20;
public:
	Blockqueue(int maxcap = defaultnum):
	maxcap_(maxcap)
	{
		pthread_mutex_init(&mutex_,nullptr);
		pthread_cond_init(&c_cond_,nullptr);
		pthread_cond_init(&p_cond_,nullptr);

		high_water_ = maxcap_ * 2 / 3;
		low_water_ = maxcap_ / 3;
	}
	void push(const T& in)
	{
		pthread_mutex_lock(&mutex_);
		while(q_.size() == maxcap_){                //防止伪唤醒 ----- if修改成while,只有满足条件才会往下走
			pthread_cond_wait(&p_cond_,&mutex_);          //伪唤醒 -- 多生产者单消费者或者多消费者单生产者或者多生产者多消费者都有可能造成
			//-- 本质是唤醒了多个线程，一起争夺锁导致的
		}
		q_.push(in);                             //不是想生产就生产，看满不满足生产条件
		// if(q_.size() >= high_water_) pthread_cond_signal(&c_cond_);
		pthread_cond_signal(&c_cond_);
		pthread_mutex_unlock(&mutex_);
	}
	const T pop()
	{
		pthread_mutex_lock(&mutex_);
		while(q_.size() == 0){                  // 必须在锁里面，防止判断q_.size()时，时间片切换线程，先添加了，导致的数据安全问题
			pthread_cond_wait(&c_cond_,&mutex_);
		}
		const T data = q_.front();       //什么时候都能消费吗？ ----有货物才能消费
		q_.pop();
		// if(q_.size() <= low_water_) pthread_cond_signal(&p_cond_);
		pthread_cond_signal(&p_cond_);
		pthread_mutex_unlock(&mutex_);
		return data;
	}
	~Blockqueue()
	{
		pthread_mutex_destroy(&mutex_);
		pthread_cond_destroy(&c_cond_);
		pthread_cond_destroy(&p_cond_);
	}
private:
	queue<T> q_;
	int maxcap_;
	pthread_mutex_t mutex_;
	pthread_cond_t c_cond_;
	pthread_cond_t p_cond_;

	int high_water_;
	int low_water_;
};


#endif 
